#ifndef AXES_HPP
#define AXES_HPP
#include "GlobalDefines.hpp"
#include "math.h"

#define AXES_X_AXIS        10
#define AXES_Y_AXIS        20
#define AXES_Z_AXIS        30

#define AXES_XYZ    11
#define AXES_XZY    21
#define AXES_YXZ    31
#define AXES_YZX    41
#define AXES_ZXY    51
#define AXES_ZYX    61
#define AXES_XYZr    71
#define AXES_XZYr    81
#define AXES_YXZr    91
#define AXES_YZXr    101
#define AXES_ZXYr    111
#define AXES_ZYXr    121


class Axes
{
private:
    Vec3d 
        x_axis,
        y_axis,
        z_axis;
    // internal support functions
    // rotation around global axes
    Vec3d _rot_G_X(Vec3d input, double angle);
    Vec3d _rot_G_Y(Vec3d input, double angle);
    Vec3d _rot_G_Z(Vec3d input, double angle);
    Vec3d _rot_L_X(Vec3d input, double angle);
    Vec3d _rot_L_Y(Vec3d input, double angle);
    Vec3d _rot_L_Z(Vec3d input, double angle);
    // rotation around arbitrary axis
    Vec3d _rot_A_A(Vec3d input, Vec3d axis, double angle);
    // hmm...
    void checkOrthogonality();

public:
    Axes();
    Axes(Vec3d rotationAngles, int AXES_ROTATION_ORDER);
    Axes(Vec3d xAxis, Vec3d yAxis, Vec3d zAxis);

    // accessors
    Vec3d getAxis(int AXES__AXIS);
    Vec3d xAxis();
    Vec3d yAxis();
    Vec3d zAxis();

    // modifiers
    void rotateAxesAroundGlobalAxis(int AXES__AXIS, double angle);
    void rotateAxesAroundLocalAxis(int AXES__AXIS, double angle);
    void rotateAxesAroundArbitraryAxis(Vec3d axis, double angle);

    // helpers
    Vec3d rotatePointAroundLocalAxis(Vec3d point, int AXES__AXIS, double angle);
    Vec3d rotatePointAroundGlobalAxis(Vec3d point, int AXES__AXIS, double angle);

    Vec3d getGlobalPointFromLocalPoint(Vec3d point);
    Vec3d getLocalPointFromGlobalPoint(Vec3d point);
};

#endif
